#include<iostream>
using namespace std;
/*
多态是C++面向对象三大特性之一
多态分为两类：
    1、静态多态：函数重载和运算符重载属于静态多态，复用函数名
    2、动态多态：派生类和虚函数实现运行时多态
静态多态和动态多态区别：
    1、静态多态的函数地址早绑定 - 编译阶段确定函数地址
    2、动态多态的函数地址晚绑定 - 运行阶段确定函数地址
*/
/*
原理：
在底层，Animal会有一个虚函数指针，指向虚函数表，此时虚函数表记录的是动物类的speak函数地址
Cat继承Animal后，也会继承虚函数指针，但是此时由于重写speak函数，Cat中的speak函数就会覆盖掉父类的speak函数地址
所以当父类指针或引用指向子类对象时，调用的是子类的speak函数
*/
class Animal
{
public:
    virtual void speak()
    {
        cout<<"动物在说话"<<endl;
    }
};
class Cat:public Animal
{
public:
    //重写：函数返回值类型 函数名 参数列表 完全相同
    void speak()
    {
        cout<<"小猫在说话"<<endl;
    }
};
class Dog:public Animal
{
public:
    void speak()
    {
        cout<<"小狗在说话"<<endl;
    }
};
//地址早绑定，在编译阶段确定函数地址
//如果想执行让猫说话，那么这个函数地址就不能提前绑定，需要在运行阶段进行绑定，地址晚绑定

//动态多态满足条件
//1有继承关系
//2子类要重写父类的虚函数

//动态多态使用
//父类的指针或者引用 指向子类对象
void doSpeak(Animal &animal)//Animal &animal = cat;
{
    animal.speak();
}
void test01()
{
    Cat cat;
    doSpeak(cat);
    Dog dog;
    doSpeak(dog);
}
int main()
{
    test01();
}